/*
 * Copyright (c) 2023 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#ifndef DEV_MCTP_H
#define DEV_MCTP_H

#include <mc/core/object.h>
#include <mctp/pcie_transport.h>

namespace dev {

typedef enum mctp_message_type {
    MCTP_MESSAGE_TYPE_MCTP_CTRL  = 0x00,
    MCTP_MESSAGE_TYPE_PLDM       = 0x01,
    MCTP_MESSAGE_TYPE_NCSI       = 0x02,
    MCTP_MESSAGE_TYPE_ETHERNET   = 0x03,
    MCTP_MESSAGE_TYPE_NVME       = 0x04,
    MCTP_MESSAGE_TYPE_SPDM       = 0x05,
    MCTP_MESSAGE_TYPE_SECUREDMSG = 0x06,
    MCTP_MESSAGE_TYPE_VDPCI      = 0x7E,
    MCTP_MESSAGE_TYPE_VDIANA     = 0x7F,
} MCTP_MESSAGE_TYPE;

typedef enum mctp_phy_medium {
    PHY_MEDIUM_PCI       = 0x0F,
    PHY_MEDIUM_SMBUS     = 0x02,
    PHY_MEDIUM_SMBUS_OEM = 0x80,
} MCTP_PHY_MEDIUM;

#define ENDPOINT_IS_DISCOVERY 0x01

constexpr std::string_view PATH_MCTP           = "/bmc/kepler/Systems/1/Mctp";
constexpr std::string_view PATH_MCTP_BINDING   = "/bmc/kepler/Systems/1/Mctp/MctpBinding";
constexpr std::string_view PATH_MCTP_ROUTING   = "/bmc/kepler/Systems/1/Mctp/Routing";
constexpr std::string_view PATH_MCTP_TRANSPORT = "/bmc/kepler/Systems/1/Mctp/Transport";
constexpr std::string_view PATH_MCTP_ENDPOINT  = "/bmc/kepler/Systems/1/Mctp/Endpoint";

constexpr std::string_view PCIE_BINGING_INTERFACE     = "bmc.kepler.Systems.Mctp.MctpBinding.PCIe";
constexpr std::string_view PCIE_ENDPOINT_INTERFACE    = "bmc.kepler.Systems.Mctp.PCIeEndpoint";
constexpr std::string_view PCIE_TRANSPORT_INTERFACE   = "bmc.kepler.Systems.Mctp.PCIeTransport";
constexpr std::string_view OBJECT_PROPERIES_INTERFACE = "bmc.kepler.Object.Properties";

#define DEVICE_NUM_OFFSET 11
#define FUNC_NUM_OFFSET   8

class MC_API mctp : public mc::core::object {
public:
    mctp(mc::engine::abstract_object* parent, uint16_t phy_addr, MCTP_MESSAGE_TYPE msg_type,
         std::string position);
    ~mctp();

    void                                   create_transport_obj(mc::dict& object);
    void try_get_endpoint_object(uint8_t retry_count, std::function<void()> cb);
    void create_transport_and_endpoint(std::string module_name, std::function<void()> cb);
    bool request(mc::dict ctx, std::vector<uint8_t>& data, int32_t timeout_ms, std::string& rsp);
    static uint16_t init_phy_addr(uint8_t bus, uint8_t device, uint8_t function) {
        return (bus & 0xFF) | ((device & 0x1F) << DEVICE_NUM_OFFSET) |
               ((function & 0x07) << FUNC_NUM_OFFSET);
    }

private:
    uint16_t                     m_phy_addr;
    MCTP_MESSAGE_TYPE            m_msg_type;
    std::string                  m_position;
    std::string                  m_mctp_name;
    std::string                  m_transport_path;
    std::string                  m_endpoint_path;
    transport_object*            m_transport_obj;
    bool                         m_create_endpoint_success = false;
    mc::engine::abstract_object* m_parent;
};

} // namespace dev

#endif // DEV_MCTP_H